💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    로딩 중이에요... 🐣

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    24 Ajax + CSRF 토큰을 활용한 좋아요 | ✅ 편저: 코담 운영자

    24강 - Ajax + CSRF 토큰을 활용한 좋아요 요청 구현

    호출, fetch, csrf


    ✅ 목표

    • PostSerializercsrf_token 필드를 추가하여, 게시글 JSON 응답 가장에 CSRF 토큰을 포함

    • Ajax(fetch) 호출 시 CSRF 토큰을 포함하여 정수적인 POST 요청 구현


    1. CSRF 토큰 배포와 Serializer 구조

    PostSerializer 개발

    from django.middleware.csrf import get_token
    
    class PostSerializer(serializers.ModelSerializer):
        comment_post = CommentSerializer(many=True)
        author = FeedAuthorSerializer()
        csrf_token = serializers.SerializerMethodField()
    
        class Meta:
            model = models.Post
            fields = (
                "id",
                "image",
                "caption",
                "image_likes",
                "author",
                "comment_post",
                "csrf_token",
            )
    
        def get_csrf_token(self, obj):
            request = self.context.get('request')
            return get_token(request) if request else None
    

    설명

    • SerializerMethodField()를 사용하여 직접 get_csrf_token() 정의

    • context['request']를 통해 현재 요청에서 CSRF 토큰 추출


    2. context 설정 방법

    뷰나 뷰셋에서 context 에 request 객체를 건너쓰면, 사이러리어에서 request 토큰 가져오기 가능

    방법 예시:

    class PostViewSet(viewsets.ModelViewSet):
        queryset = models.Post.objects.all()
        serializer_class = PostSerializer
    
        def get_serializer_context(self):
            context = super().get_serializer_context()
            context['request'] = self.request
            return context
    

    토큰 포함 Ajax 호출 - JS 구현

    파일: django_instagram/static/js/posts/loadMorePosts.js

    // 좋아요 / 좋아요 취소 Ajax 호출
    async function handleLikeClick(postId, csrfToken, target) {
      console.log("handleLikeClick  : ", postId, csrfToken, target);
      const iTag = target.querySelector("i");
      const likeButton = target;
    
      if (likeButton.disabled) return;
      likeButton.disabled = true;
    
      try {
        const response = await fetch(`/api/posts/${postId}/post_like/`, {
          method: "POST",
          headers: {
            "X-CSRFToken": csrfToken,
          },
        });
    
        const data = await response.json();
        console.log("response  : ", data);
    
        if (!response.ok || !data.success) {
          console.log(" 좋아요 API 호출 중 오류가 발생했습니다.: ", data.error);
          throw new Error(data.message || "좋아요 API 호출 중 오류가 발생했습니다.");
        }
    
        if (data.message === "like") {
          iTag.classList.replace("fa-heart-o", "fa-heart");
          iTag.classList.replace("text-gray-500", "text-red-500");
        } else {
          iTag.classList.replace("fa-heart", "fa-heart-o");
          iTag.classList.replace("text-red-500", "text-gray-500");
        }
    
        target.querySelector("#like-count-" + postId).innerText = data.like_count;
      } catch (error) {
        console.error("Error liking post:", error);
      } finally {
        likeButton.disabled = false;
      }
    }
    

    ✅ 요약

    • Django에서 CSRF 토큰은 보안을 위해 필요

    • PostSerializer에서 get_csrf_token()을 통해 CSRF 토큰을 전달

    • 뷰셋에서 context['request'] = self.request 처리 필수

    • JS에서 fetch 요청 시 헤더에 "X-CSRFToken" 값을 포함해야 서버가 요청을 허용함

    이 방식을 통해 API와 JS 간의 안전한 POST 요청 구현이 가능합니다.

    TOP
    preload preload